<?php
/**************************************************
 *                                                *
 *        name: class view                        * 
 *        说明: MCPHP 的核心视图类                *
 *              参考了 heiyeluren 的TMPHP中的类   *
 *              目前支持自定义的MC_DynaPageTmpl、MC_StaticPageTmpl和Smarty 三种模板
 *              其中MC_DynaPageTmpl 是动态创建的HTML页面
 *              MC_StaticPageTmpl 是加载一个静态的HMTL模板页，之后对相应的内容做替换即可
 *      author: fenghao                           *
 *        date: 2012-03-20                        *
 *      update: 2012-07-08                        *
 *              更新 class MC_View_sta 使用信模板   *
 *                                                *
 **************************************************/

class MC_View{
    
    /**
     * @var 视图类型为原生模板（对应class.MC_DynaPageTmpl.php）
     */
    const TYPE_DYN = 'php';

    /**
     * @var 视图类型为旧版原生模板（对应class.MC_StaticPageTmpl.php）
     */
    const TYPE_STA = 'html';

    /**
     * @var 视图类型为Smart
     */
    const TYPE_SMARTY = 'smarty';

    /**
     * @var object 对象单一实例
     */
    static $_instance = null;

    /**
     * 保证对象不被clone
     */
    private function __clone(){}

    /** 
     * 构造函数
     */
    private function __construct(){}

    /**
     * 视图创建的工厂方法
     *
     * @param string $controller
     * @return obj
     */

    public static function factory($controller, $viewtype='', $params = array() ){

        $viewtype = strtolower($viewtype);
        
        if ($viewtype == ''){
            $viewtype = self::TYPE_DYN;
        }

        switch($viewtype){
            case self::TYPE_DYN:
                $obj = MC_View_php::getInstance($controller, $params);
                break;
            case self::TYPE_STA:
                $obj = MC_View_sta::getInstance($controller, $params);
                break;
            case self::TYPE_SMARTY:
                $obj = MC_View_smarty::getInstance($controller, $params);
                break;

            default:
                throw MC_Exception("View type $viewtype not support");
        }
        return $obj;
    }
}

/**
 * 使用 MC_DynaPageTmpl 的模板视图类
 *
 */
class MC_View_php{
    /**
     * @var object 对象单例
     */
    static $_instance = NULL;
    /**
     * @var object 控制器对象
     */
    public $controller = NULL;
    /**
     * @var bool 是否调试模式
     */
    public $debug = false;
    /**
     * @var array 传递过来的一些参数
     */
    public $param;

    /**
     * 保证对象不被clone
     */
    private function __clone() {}

    /**
     * 构造函数
     */
    private function __construct($controller, $_param=null) {
        $this->controller = $controller;
        $this->param = $_param;
    }


    /**
     * 获取对象唯一实例
     *
     * @param void
     * @return object 返回本对象实例
     */
    public static function getInstance($controller, $params){
        if (!(self::$_instance instanceof self)){
            self::$_instance = new self($controller, $params);
        }
        return self::$_instance;
    }
    
    /**
     * 设置模板相应的调试模式
     *
     * @param bool $debug 是否调试模式，true or false
     * @return void
     */
    public function setDebug($debug = false){
        $this->debug = $debug;
    }

 
    /**
     * 解析处理一个模板文件
     *
     * @param  string $viewname  视图类的名称
     * @param  array  $vars 需要给模板变量赋值的变量
     * @return void
     */
    public function renderFile($viewname, $vars) {
        $conf = __get_config('HTMLTemp');
        if($viewname != ''){
            $filePath = APPS_DIR.'/'.__get_config('Apps.AppName')."/view/".$class.".class.php";
            if(!is_file($filePath) || !is_readable($filePath)){
                throw new MC_Exception("View file ".$filePath." not exist or not readable");
            }
        }

        //实例化模板类
        $tmpl = require_once($filePath);

        //添加具体内容
        if(!empty($vars)){
            $_a = $vars['head'];
            foreach($_a as $value){
                $tmpl->addHead($value);
            }
            $_a = $vars['body'];
            foreach($_a as $key => $value){
                $tmpl->addHtmlSym($key, $value);
            }
                
        } 

        //生成HTML页面，可以直接显示 
        $tmpl->show();

        if($this->debug){
            echo "\n<br/>\n";
            var_dump($vars);
            echo "\n<br/>\n";
        } 
        
    }

}

/**
 * 使用 MC_StaticPageTmpl 的模板视图
 * 
 */
class MC_View_sta{
    /**
     * @var object 对象单例
     */
    static $_instance = NULL;
    /**
     * @var object 控制器对象
     */
    public $controller = NULL;
    /**
     * @var array 传递过来的一些参数
     */
    public $param;
    /**
     * @var bool 是否调试模式
     */
    public $debug = false;


    /**
     * 保证对象不被clone
     */
    private function __clone() {}

    /**
     * 构造函数
     */
    private function __construct($controller, $_param=null) {
        $this->controller = $controller;
        $this->param = $_param;
    }


    /**
     * 获取对象唯一实例
     *
     * @param void
     * @return object 返回本对象实例
     */
    public static function getInstance($controller, $params){
        if (!(self::$_instance instanceof self)){
            self::$_instance = new self($controller, $params);
        }
        return self::$_instance;
    }
    

    /**
     * 设置模板相应的调试模式
     *
     * @param bool $debug 是否调试模式，true or false
     * @return void
     */
    public function setDebug($debug = false){
        $this->debug = $debug;
    }

 
    /**
     * 解析处理一个模板文件
     *
     * @param  string $filePath  模板文件路径
     * @param  array  $vars 需要给模板变量赋值的变量
     * @return void
     */
    public function renderFile($filename, $vars) {
        $conf = __get_config('HTMLTemp');
		$conf['cache_dir'] = APPS_DIR.'/'.__get_config('Apps.AppName').'/'.$conf["cache_dir"];
        if($filename != ''){
            $filePath = APPS_DIR.'/'.__get_config('Apps.AppName').'/'.$conf['temp_dir'].DS.$filename;
            if(!is_file($filePath) || !is_readable($filePath)){
                throw new MC_Exception("View file ".$filePath." not exist or not readable");
				return false;
            }
        }else{
            throw new MC_Exception("View file ".$filePath." not exist or not readable");
			return false;
		}
		
		//转换传过来的变量
        if(!empty($vars)){
            foreach($vars as $key=>$value){
				$$key = $value;
		//var_dump($$key);
            }
        } 
		

        //实例化模板类
		//使用controller名+action名作为缓存文件名称
		$cache_file = $this->controller->controllerName."_".$this->controller->actionName."_".basename($filename);
		$ld = isset($conf['left_delimiter'])?$conf['left_delimiter']:'{';
		$rd = isset($conf['right_delimiter'])?$conf['right_delimiter']:'}';
		
        $tmpl = new MC_StaticPageTmpl($filePath, $conf["cache_dir"], $cache_file, $ld, $rd);
    
        //加载模板
        $tmpl->loadTemplete();
		
		require_once $conf["cache_dir"]."/".$cache_file;


        if($this->debug){
            echo "\n<br/>\n";
            var_dump($vars);
            echo "\n<br/>\n";
        } 
        
    }

}


/**
 * Smarty文件模板视图类
 *
 * @desc 针对 Smarty Template 的模板View的模板加载
 *
 * 相关链接：
 *相关链接Smarty官网：http://www.smarty.net/
 *netSmarty手册：http://www.phpchina.com/manual/smarty/
 *smartySmarty入门：http://www.google.cn/search?q=%E8%8F%9C%E9%B8%9F%E5%AD%A6PHP%E4%B9%8BSmarty%E5%85%A5%E9%97%A8&btnG=Google+%E6%90%9C%E7%B4%A2
 * 
 * 这部分代码是从 heiyeluren 的　TMPHP　中拷贝过来的，这里只是作为对Smarty 的支持，具体没有测试
 */
class MC_View_smarty
{

    /**
     * @var object 对象单例
     */
    static $_instance = NULL;
    /**
     * @var object 控制器对象
     */
    public $controller = NULL;
    /**
     * @var array Smarty对象参数
     */
    public $params = array();
    /**
     * @var bool 是否调试模式
     */
    public $debug = false;


    /**
     * 保证对象不被clone
     */
    private function __clone() {}

    /**
     * 构造函数
     *
     * @param object $controller 控制器对象
     *
     * @param array $params 需要传递的选项参数
     *
     * 参数说明：
     * $params = array(
        'template_dir'array=> 'view/',参数说明//指定模板文件存放目录，缺省为 view 目录
        'cache_dir'view=> 'cache/smarty/cache',cache//指定缓存文件存放目录
        'compile_dir'指定缓存文件存放目录=> 'cache/smarty',指定缓存文件存放目录//Smarty编译目录
        'config_dir'编译目录=> '',cache//Smarty配置文件目录, 缺省为空
        'left_delimiter'left_delimiter=> '{{',cache//模板变量的左边界定符, 缺省为 {{
        'right_delimiter'right_delimiter=> '}}',left_delimiter//模板变量的右边界定符，缺省为 }}
       );

     */
    private function __construct($controller, $params) {
        $this->controller = $controller;
        $this->params = $params;
    }


    /**
     * 获取对象唯一实例
     *
     * @param void
     * @return object 返回本对象实例
     */
    public static function getInstance($controller, $params){
        if (!(self::$_instance instanceof self)){
            self::$_instance = new self($controller, $params);
        }
        return self::$_instance;
    }
    
    /**
     * 设置模板相应的调试模式
     *
     * @param bool $debug 是否调试模式，true or false
     * @return void
     */
    public function setDebug($debug = false){
        $this->debug = $debug;
    }

 
    /**
     * 解析处理一个模板文件
     *
     * @param  string $filePath  模板文件路径
     * @param  array  $vars 需要给模板变量赋值的变量
     * @return void
     */
    public function renderFile($filePath, $vars) {
        //加载Smarty
        load_plugin("Smarty/Smarty");
        $smarty = new Smarty;

        //判断是否传递配置参数
        if ( empty($this->params) || !isset($this->params['compile_dir']) || !isset($this->params['config_dir']) || !isset($this->params['cache_dir'])){
            throw new MC_Exception("Smarty template engine configure [compile_dir,config_dir,cache_dir] not set, please  MC_View->factory() entry params"); 
        }

        //设置Smarty参数
        $smarty->template_dir    = !isset($this->params['template_dir']) ? (APPS_DIR.'/'.__get_config('Apps.AppName')."/view") : $this->params['template_dir'];
        $smarty->compile_dir     = $this->params['compile_dir']; 
        $smarty->config_dir      = $this->params['config_dir'];
        $smarty->cache_dir       = $this->params['cache_dir'];
        $smarty->left_delimiter  = !isset($this->params['left_delimiter']) ? "{{" : $this->params['left_delimiter'];
        $smarty->right_delimiter = !isset($this->params['right_delimiter']) ? "}}" : $this->params['right_delimiter'];
        $smarty->debugging = $this->debug;

        //检查模板文件
        if(!is_file($filePath) || !is_readable($filePath)){
            throw new MC_Exception("View file ". $filePath ." not exist or not readable");
        }
        //设置模板变量
        if (!empty($vars)){
            foreach($vars as $key => $value){
                $smarty->assign($key, $value);
            }
        }
        $smarty->display($filePath);
    }

}


?>
